package gientech.spring.micro.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import gientech.spring.micro.dto.UserChangeEvent;
import gientech.spring.micro.entity.User;
import gientech.spring.micro.mapper.UserMapper;

import gientech.spring.micro.service.UserService;

import gientech.spring.micro.util.BloomFilterUtil;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;


@Service
@CacheConfig(cacheNames = "user")
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {

    private HashMap<String, User> userMap = new HashMap<>();

    // 预期插入数量
    static long expectedInsertions = 200L;
    // 误判率
    static double falseProbability = 0.01;

    // 非法请求所返回的JSON
    static String illegalJson = "[\"com.company.springboot.entity.User\",{\"id\":null,\"userName\":\"null\",\"sex\":null,\"age\":null}]";

    private RBloomFilter<Long> bloomFilter = null;

    @Resource
    private BloomFilterUtil bloomFilterUtil;

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private UserMapper userMapper;

    @PostConstruct // 项目启动的时候执行该方法，也可以理解为在spring容器初始化的时候执行该方法
    public void init() {
        // 启动项目时初始化bloomFilter
        List<User> userList = this.list();
        bloomFilter = bloomFilterUtil.create("idWhiteList", expectedInsertions, falseProbability);
        for (User user : userList) {
            bloomFilter.add(Long.valueOf(user.getUId()));
        }
    }


    @Override
    @CachePut(cacheNames = "user", key = "#user.id")
    public void addUser(User user) {
        userMapper.insert(user);
        // 新生成key的加入布隆过滤器，此key从此合法
        bloomFilter.add(Long.parseLong(user.getUId()));


    }
    @Override
    @Cacheable(cacheNames = "user", key = "#id", unless = "#result==null")
    public User getUserById(Long id) {
        // bloomFilter中不存在该key,为非法访问
        if (!bloomFilter.contains(id)) {
            System.out.println("所要查询的数据既不在缓存中，也不在数据库中，为非法key");

            redissonClient.getBucket("user::" + id, new StringCodec()).set(illegalJson, new Random().nextInt(200) + 300, TimeUnit.SECONDS);
            return null;
        }
        // 不是非法访问，可以访问数据库
        System.out.println("数据库中得到数据*****");
        return userMapper.selectById(id);
    }
    @Override
    @CachePut(key = "#user.username")
    public User updateUser(User user) {
        userMapper.updateById(user);
        // 新生成key的加入布隆过滤器，此key从此合法,因为该更新方法并不更新id,所以也不会产生新的合法的key
        bloomFilter.add(Long.valueOf(user.getUId()));
        // 返回新对象信息
        return user;
    }
    @Override
    @CacheEvict(cacheNames = "user", key = "#id")
    public boolean delete(Long id) {
        // 删除数据库中具有的数据,就算此key从此之后不再出现，也不能从布隆过滤器删除
        return userMapper.deleteById(id) == 1;
    }

    @Override
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void doupdateUser(UserChangeEvent userChangeEvent) {

        int isExistTx = userMapper.isExistTx(userChangeEvent.getTxNo());
        if(isExistTx == 0){
            userMapper.updateById(userChangeEvent.getUId(),userChangeEvent.getUUsername());
            userMapper.addTx(userChangeEvent.getTxNo());
        }

    }


}




